package com.fjwt.gz.mgr.ctrl.sysuser;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjwt.gz.core.aop.MethodLog;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.db.entity.SysUser;
import com.fjwt.gz.db.entity.SysUserRoleRela;
import com.fjwt.gz.db.vo.SysUserRoleRelaVO;
import com.fjwt.gz.mgr.ctrl.CommonCtrl;
import com.fjwt.gz.mgr.service.AuthService;
import com.fjwt.gz.service.impl.SysUserAuthService;
import com.fjwt.gz.service.impl.SysUserRoleRelaService;
import com.fjwt.gz.service.impl.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/*
* 操作员列表
*
* @author wg
* @site https://pt.jdyd.xyz/
* @date 2021/6/8 17:13
*/
@RestController
@RequestMapping("/api/sysUsers")
@Slf4j
public class SysUserController extends CommonCtrl {

	@Autowired private SysUserService sysUserService;
	@Autowired private SysUserAuthService sysUserAuthService;
	@Autowired private AuthService authService;
	@Autowired private SysUserRoleRelaService sysUserRoleRelaService;

	/** list */
	@PreAuthorize("hasAnyAuthority( 'ENT_UR_USER', 'ENT_UR_USER_SEARCH' )")
	@RequestMapping(value="", method = RequestMethod.GET)
	public ApiRes list() {

		SysUser queryObject = getObject(SysUser.class);

		long count = sysUserService.queryCount(queryObject);
		if (count <=0 ) {
			return ApiRes.page(new Page());
		}

		List<JSONObject> list = sysUserService.selectList(getIPage(), queryObject);
		//通过查出来的操作员list列表来查出对应的角色名称和角色id
		List<Long> sysUserIdList = list.stream()
				.map(json -> json.getLong("sysUserId"))
				.toList();
		List<SysUserRoleRelaVO> userRoleRelaList = sysUserRoleRelaService.getBaseMapper().getRolesByUserIds(sysUserIdList);
		Map<Long, List<SysUserRoleRelaVO>> userIdMap = new HashMap<>();
		if (CollUtil.isNotEmpty(userRoleRelaList)) {
			userIdMap = userRoleRelaList.stream().collect(Collectors.groupingBy(SysUserRoleRelaVO::getUserId));
		}

		Map<Long, List<SysUserRoleRelaVO>> finalUserIdMap = userIdMap;
		list.forEach(item -> {
			// 数据脱敏
			item.put("telphone", DesensitizedUtil.mobilePhone(item.getString("telphone")));
			item.put("realname", DesensitizedUtil.chineseName(item.getString("realname")));
			if (CollUtil.isNotEmpty(finalUserIdMap)) {
				item.put("roles", finalUserIdMap.get(item.getLong("sysUserId")));
			}
		});

		return ApiRes.page(getIPage(), list, count);
	}


	/** detail */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_VIEW' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.GET)
	public ApiRes detail(@PathVariable("recordId") Integer recordId) {


		SysUser sysUser = sysUserService.getById(recordId);
		//添加用户的角色详情
		List<JSONObject> roles = sysUserRoleRelaService.getBaseMapper().getRoles(sysUser.getSysUserId());
		if (null!=roles && !roles.isEmpty()){
			sysUser.addExt("roles",roles);
		}
		log.info("操作员详情，请求地址：/api/sysUsers/{}，响应结果:{}",  recordId, sysUser);
		return ApiRes.ok(sysUser);
	}

	/** add */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_ADD' )")
	@MethodLog(remark = "添加管理员")
	@RequestMapping(value="", method = RequestMethod.POST)
	public ApiRes add() {
		SysUser sysUser = getObject(SysUser.class);
		String loginPassword = getValString("loginPassword");
		String roleIds = getValString("roleIds");
		if (sysUser.getUserType().equals(SysUser.UEST_TYPE_ADMIN)) {
			//查询是否已存在超级管理员
			List<SysUser> sysUserList = sysUserService.list(SysUser.gw()
					.eq(SysUser::getSysType, Constants.SYS_ROLE_TYPE.MANAGER)
					.eq(SysUser::getUserType, SysUser.UEST_TYPE_ADMIN));
			if (CollUtil.isNotEmpty(sysUserList)) {
				return ApiRes.customFail("已存在超级管理员！请选择其他角色");
			}
		}

		if (StringUtils.isBlank(loginPassword)) {
			loginPassword = null;
		}
		sysUser.setBelongInfoId("0");
		sysUserService.addSysUser(sysUser, CS.SYS_ROLE_TYPE.MANAGER, loginPassword);
		//分配用户角色
		if (StringUtils.isNotEmpty(roleIds)){
			List<String> roleIdList = JSONArray.parseArray(roleIds, String.class);
			sysUserService.saveUserRole(sysUser.getSysUserId(), roleIdList);

		}
		return ApiRes.ok();
	}

	/** update */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_EDIT' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.PUT)
	@MethodLog(remark = "修改操作员信息")
	public ApiRes update(@PathVariable("recordId") Long recordId) {
		SysUser sysUser = getObject(SysUser.class);
		sysUser.setSysUserId(recordId);
		String roleIds = getValString("roleIds");

		//判断是否自己禁用自己
		if(recordId.equals(getCurrentUser().getSysUser().getSysUserId()) && sysUser.getState() != null && sysUser.getState() == CS.PUB_DISABLE){
			throw new BizException("系统不允许禁用当前登陆用户！");
		}
		//超管用户不可重复
		if (com.fjwt.gz.core.entity.SysUser.UEST_TYPE_ADMIN == sysUser.getUserType()) {
			if (sysUserService.count(SysUser.gw()
					.ne(SysUser::getSysUserId, recordId)
					.eq(SysUser::getUserType, com.fjwt.gz.core.entity.SysUser.UEST_TYPE_ADMIN)
					.eq(SysUser::getBelongInfoId, sysUser.getBelongInfoId())) > 0) {
				throw new BizException("超管用户已存在！");
			}
		}
		//判断是否重置密码
		Boolean resetPass = getReqParamJSON().getBoolean("resetPass");
		if (resetPass != null && resetPass) {
			String updatePwd = getReqParamJSON().getBoolean("defaultPass") == false ? Base64.decodeStr(getValStringRequired("confirmPwd")) : null;

			// 查询所属用户的系统类型（ 不一定是运营平台用户 ）
			SysUser sysUserDB = sysUserService.getById(recordId);
			sysUserAuthService.resetAuthInfo(recordId, null, null, true, updatePwd, sysUserDB.getSysType());
			// 删除用户redis缓存信息
			authService.delAuthentication(Arrays.asList(recordId));
		}



		sysUserService.updateSysUser(sysUser, true);
		//分配用户角色
		if (StringUtils.isNotEmpty(roleIds) && sysUser.getUserType() != 1){
			List<String> roleIdList = JSONArray.parseArray(roleIds, String.class);
			sysUserService.saveUserRole(sysUser.getSysUserId(), roleIdList);

		}
		//如果修改为超级管理员 清除用户角色
		if (sysUser.getUserType() == 1) {
			sysUserRoleRelaService.remove(SysUserRoleRela.gw().eq(SysUserRoleRela::getUserId, sysUser.getSysUserId()));
		}

		//如果用户被禁用，需要更新redis数据
		if(sysUser.getState() != null && sysUser.getState() == CS.PUB_DISABLE){
			authService.refAuthentication(Arrays.asList(recordId));
		}

		// 返回最新用户信息
		SysUser dbRecord = sysUserService.getById(recordId);
		log.info("修改操作员信息，请求地址：/api/sysUsers/{}，响应结果:{}",  recordId, dbRecord);
		return ApiRes.ok(dbRecord);
	}

	/** delete */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_DEL' )")
	@RequestMapping(value="/{recordId}", method = RequestMethod.DELETE)
	@MethodLog(remark = "删除操作员信息")
	public ApiRes delete(@PathVariable("recordId") Long recordId) {

		//查询该操作员信息
		SysUser sysUser = sysUserService.getById(recordId);
		if (sysUser == null) {
			throw new BizException("该操作员不存在！");
		}

		//判断是否自己删除自己
		if(recordId.equals(getCurrentUser().getSysUser().getSysUserId())){
			throw new BizException("系统不允许删除当前登陆用户！");
		}
		// 删除用户
		sysUserService.removeUser(sysUser, CS.SYS_ROLE_TYPE.MANAGER);

		//如果用户被删除，需要更新redis数据
		authService.refAuthentication(Arrays.asList(recordId));

		return ApiRes.ok();
	}



	/** 解除登录失败次数限制 */
	@PreAuthorize("hasAuthority( 'ENT_UR_USER_LOGIN_LIMIT_DEL' )")
	@RequestMapping(value="/loginLimit/{recordId}", method = RequestMethod.DELETE)
	@MethodLog(remark = "解除登录限制")
	public ApiRes deleteLoginLimit(@PathVariable("recordId") Long recordId) throws BizException{

		SysUser sysUser = sysUserService.getById(recordId);
		if (ObjectUtils.isEmpty(sysUser)) {
			return ApiRes.ok();
		}

		String sysType = sysUser.getSysType();

		if (CS.SYS_ROLE_TYPE.MANAGER.equals(sysType)) {
			RedisUtil.del(CS.getCacheKeyLoginErr(CS.SYS_ROLE_TYPE.MANAGER, sysUser.getTelphone()));
		}

		return ApiRes.ok();
	}

}
